﻿#ifndef __SS_ID_MANAGER_H__
#define __SS_ID_MANAGER_H__
#include <set>
#include <deque>
#include <algorithm>

namespace StarSeeker
{
/////////////////////////////////重复ID分配器///////////////////////////////
template<class T>
class ssReuseID
{
public:
	// 构造、析构
	ssReuseID(void)
	{
		m_minID = 0;
		m_maxID = 0;
		m_idCount = 0;
		m_idFree.clear();
		m_idUse.clear();
		m_isUpset = false;
	}
	//必须>0
	bool Init(T min, T max, bool isUpset=false)
	{
		if (min <= 0 || max <= 0 || min >= max)
		{
			return false;
		}
		m_minID = min;
		m_maxID = max;
		m_idCount = max - min;
		if (m_idCount > 0)
		{
			for (T i = m_minID; i <= m_maxID; ++i)
			{
				m_idFree.push_back(i);
			}
			if (m_isUpset)
				std::random_shuffle(m_idFree.begin(), m_idFree.end());
			return true;
		}
		return false;
	}
	//重置
	void Reset()
	{
		m_idFree.clear();
		m_idUse.clear();
		if (m_idCount > 0)
		{
			for (T i = m_minID; i <= m_maxID; ++i)
			{
				m_idFree.push_back(i);
			}
			if (m_isUpset)
				std::random_shuffle(m_idFree.begin(), m_idFree.end());
		}
	}
	//获取一个ID，0表示失败
	T AttachID()
	{
		T id = 0;
		if (m_idCount > 0)
		{
			if (!m_idFree.empty())
			{
				id = m_idFree.front();
				m_idFree.pop_front();
				m_idUse.insert(id);
			}
		}
		return id;
	}
	//回收一个ID
	bool DetachID(T id)
	{
		if (m_idCount > 0)
		{
			typename std::set<T>::iterator itr = m_idUse.find(id);
			if (itr != m_idUse.end())
			{
				m_idFree.push(id);
				m_idUse.erase(itr);
				return true;
			}
		}
		return false;
	}

private:
	T					m_minID;
	T					m_maxID;
	T					m_idCount;
	std::deque<T>		m_idFree;
	std::set<T>			m_idUse;
	bool				m_isUpset;
};
///////////////////////////////////////////////////////////////////////////
/////////////////////////////累加ID分配器///////////////////////////////////
template<class T>
class ssCumulationID
{
public:
	// 构造、析构
	ssCumulationID(void)
	{
		m_minID = 0;
		m_maxID = 0;
		m_idCount = 0;
		m_curID = 0;
	}
	//int范围从1到2100000000之间，0保留
	//uint范围从1到4100000000之间，0保留
	bool Init(T min = 1, T max = 4100000000)
	{
		if (min <= 0 || max <= 0 || min >= max)
		{
			return false;
		}
		m_minID = min;
		m_maxID = max;
		m_idCount = max - min + 1;
		m_curID = min - 1;
		return true;
	}

	void Reset()
	{
		if (m_idCount > 1)
		{
			m_curID = m_minID - 1;
		}
	}

	T GetID()
	{
		if (m_idCount > 1)
		{
			++m_curID;
			if (m_curID > m_maxID)
			{
				m_curID = m_minID;
			}
			return m_curID;
		}
		return 0;
	}

private:
	T		m_minID;
	T		m_maxID;
	T		m_idCount;
	T		m_curID;
};
//////////////////////////////////////////////////////////////////////////
}
#endif
